package com.cl.blog.web.client.task;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cl.blog.common.RedisHashKey;
import com.cl.blog.document.ContentAndUser;
import com.cl.blog.document.Ranking;
import com.cl.blog.entity.BContent;
import com.cl.blog.entity.BUser;
import com.cl.blog.entity.BUserFollow;
import com.cl.blog.mapper.BContentMapper;
import com.cl.blog.mapper.BContentReviewMapper;
import com.cl.blog.mapper.BUserLikeMapper;
import com.cl.blog.mapper.BUserMapper;
import com.cl.blog.service.*;
import com.cl.blog.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author 付
 * @Date 2024-04-02 12:22
 * @Version 1.0
 * @description 处理历史浏览持久化的定时任务
 * @since 1.0
 */
@Slf4j
public class RankTask extends QuartzJobBean {

	@Autowired
	RedisUtil redisUtil;
	private static final String RANKING = RedisHashKey.RANKING.getType();
	private static final String WEEK_RANKING = RedisHashKey.WEEK_RANKING.getType();
	@Autowired
	BUserLikeMapper bUserLikeMapper;
	@Autowired
	BUserMapper bUserMapper;

	@Autowired
	BContentMapper bContentMapper;

	// 收藏表
	@Autowired
	BCollectService bCollectService;

	// 文章评论
	@Autowired
	BContentReviewMapper bContentReviewMapper;
	// 历史观看
	@Autowired
	BHistoryLookService bHistoryLookService;

	//用户关注
	@Autowired
	BUserFollowService bUserFollowService;
	@Autowired
	BUserLikeService bUserLikeService;

	/**
	 * 用来从redis中的hash中获取浏览量缓存的键值对，间隔时间存入mysql
	 *
	 * @param context
	 * @throws JobExecutionException
	 */
	@Override
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		log.info("绑定更新");
		LocalDateTime week = LocalDateTime.now().minus(7, ChronoUnit.DAYS);
		//获取所有用户
		List<BUser> list = bUserMapper.selectList(new QueryWrapper<BUser>());
		List<Integer> ids = list.stream().map(BUser::getId).collect(Collectors.toList());
		// 周榜数据
		for (Integer id : ids) {
			// 总排行
			// 关注度
			Long followCount = bUserFollowService.count(new QueryWrapper<BUserFollow>()
					.eq("follow_user_id", id)
			);
			// 收藏
			Long collectCount = bContentMapper.getCollectCount(id);
			Long like = bContentMapper.getLikeCount(id);
			Long history = bContentMapper.getHistory(id);

			if (followCount == null) {
				followCount = 0L;
			}
			if (collectCount == null) {
				collectCount = 0L;
			}
			if (like == null) {
				like = 0L;
			}
			if (history == null) {
				history = 0L;
			}

			double userRanking = followCount * 0.35 + collectCount * 0.4 + like * 0.2 + history * 0.05;
			// 周排行
			//关注度
			Long weekFollowCount = bUserFollowService.count(new QueryWrapper<BUserFollow>()
					.eq("follow_user_id", id)
					.between("create_time", week, LocalDateTime.now())
			);
			Long weekCollect = bContentMapper.getCollectCountWeek(id);
			Long weekLike = bUserLikeMapper.getWeekCount(id);

			if (weekCollect == null) {
				weekCollect = 0L;
			}
			if (weekFollowCount == null) {
				weekFollowCount = 0L;
			}

			double userWeekRanking = weekFollowCount * 0.35 + weekCollect * 0.4 + weekLike * 0.2 + history * 0.05;


			redisUtil.zAdd(RedisHashKey.RANKING.getType(), String.valueOf(id), -userRanking);
			redisUtil.zAdd(RedisHashKey.WEEK_RANKING.getType(), String.valueOf(id), -userWeekRanking);
		}

		// 将数据存储到缓存，一天时间过期，并更新
		Set<ZSetOperations.TypedTuple<String>> typedTuples1 = redisUtil.zRangeWithScores(RedisHashKey.RANKING.getType(), 0, 5);
		Set<ZSetOperations.TypedTuple<String>> typedTuples = redisUtil.zRangeWithScores(RedisHashKey.WEEK_RANKING.getType(), 0, 5);
		System.out.println("排行榜数据--->" + typedTuples1);
		System.out.println("周榜数据--->" + typedTuples);
		ArrayList<Ranking> rankings = new ArrayList<>();
		ArrayList<Ranking> weekRanking = new ArrayList<>();
		for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples1) {
			Ranking ranking = new Ranking();
			ranking.setUserId(Integer.valueOf(typedTuple.getValue()));
			ranking.setScore(typedTuple.getScore());
			rankings.add(ranking);
		}
		for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {
			Ranking ranking = new Ranking();
			ranking.setUserId(Math.abs(Integer.valueOf(typedTuple.getValue())));
			ranking.setScore(Math.abs(typedTuple.getScore()));
			weekRanking.add(ranking);
		}

		System.out.println(MapUtil.builder().put("ranking", rankings).put("weekRanking", weekRanking).build());
	}
}

